#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# @Project:     python_framework
# @File:        u_path.py
# @Author:      Fan GuiChuan
# @Date:        2024/7/4 16:24
# @Version:     Python3.7
# @Description: 路径管理类
import os.path
import sys
from shutil import rmtree


class PathManager(object):
    @staticmethod
    def get_root_path():
        if hasattr(sys, 'frozen'):
            return os.path.dirname(sys.executable)
        else:
            return os.path.dirname(
                os.path.dirname(os.path.abspath(__file__))
            )

    @staticmethod
    def get_config_path():
        config_path = PathManager.path_join(PathManager.get_root_path(),
                                            "logs")
        if not PathManager.path_exists(config_path):
            PathManager.make_dir(config_path)
        return config_path

    @staticmethod
    def path_join(*_path):
        return os.path.join(*_path)

    @staticmethod
    def linux_path_join(*_path):
        """
        如果使用os.path.join，连接符会根据运行环境操作系统变化。
        所以封装这个函数用于确定时linux系统的路径拼接。
        :param _path:
        :return: str 拼接后的路径
        """
        return_path = ""
        for s_path in _path:
            return_path = return_path + s_path + "/"

        return return_path[:-1]

    @staticmethod
    def windows_path_join(*_path):
        """
        如果使用os.path.join，连接符会根据操作系统变化。
        所以封装这个函数用于确定是windows系统的路径拼接
        :param _path:
        :return: str 拼接后的路径
        """
        return_path = ""
        for s_path in _path:
            return_path = return_path + s_path + "\\"

        return return_path[:-1]

    @staticmethod
    def format_to_linux_path(_path: str):
        """
        将路径格式化为linux格式，即所有的"\\"连接符都改成"/"
        :param _path:
        :return:
        """
        return _path.replace("\\", "/")

    @staticmethod
    def format_to_windows_path(_path: str):
        """
        将路径格式化为windows格式，即所有的"/"都替换为"\\"
        ：param _path:
        :return:
        """
        return _path.replace("/", "\\")

    @staticmethod
    def make_dir(dir_name: str):
        """
        创建一个目录，如果路径存在，但不是目录，则抛出异常，如果目录存在，则直接返回，否则创建
        """
        if PathManager.path_exists(dir_name) and not PathManager.is_dir(dir_name):
            raise FileExistsError(f"{dir_name} exists, but not dir!")
        os.makedirs(dir_name, exist_ok=True)

    @staticmethod
    def make_sub_dir(parent_path: str, sub_dir_name: str):
        """
        在父目录下创建子目录，返回全路径，以路径分隔符结尾
        """
        full_path = os.path.join(parent_path, sub_dir_name)
        os.makedirs(full_path, exist_ok=True)
        if os.name == "posix":
            full_path += "/"
        elif os.name == "nt":
            full_path += "\\"

        return full_path

    @staticmethod
    def file_or_dir_copy(src_path: str, dst_path: str):
        """
        文件或文件夹拷贝
        """
        if not PathManager.path_exists(src_path) or not PathManager.path_exists(dst_path):
            raise FileNotFoundError("source or dest dir not found!")

        if os.name == "posix":
            cmd = f"cp {src_path} {dst_path}"
        elif os.name == "nt":
            cmd = f"copy {src_path} {dst_path}"
        else:
            raise SyntaxError("not support system")

        os.system(cmd)

    @staticmethod
    def get_path_seperator():
        """
        获取系统路径分隔符
        """
        if os.name == "nt":
            return "\\"
        else:
            return "/"

    @staticmethod
    def remake_sub_dir(parent_path: str, sub_dir_name: str):
        """
        清空子文件夹
        """
        full_path = os.path.join(parent_path, sub_dir_name)
        if os.path.exists(full_path):
            PathManager.force_remake_dir(full_path)
        else:
            PathManager.make_sub_dir(parent_path, sub_dir_name)
        return full_path

    @staticmethod
    def force_remake_dir(dir_: str):
        """
        清空文件夹
        """
        if os.path.exists(dir_):
            rmtree(dir_)
            os.makedirs(dir_)
        else:
            parent = os.path.dirname(dir_)
            child = os.path.basename(dir_)
            PathManager.make_sub_dir(parent, child)

    @staticmethod
    def remove_dir(dir_: str):
        """
        删除指定文件夹
        """
        if os.path.exists(dir_):
            rmtree(dir_)

    @staticmethod
    def remove_file(file_: str):
        """
        删除指定文件
        """
        if PathManager.path_exists(file_):
            os.remove(file_)

    @staticmethod
    def base_name(_object: str):
        """
        获取对象的名称，对象可以是文件，也可以是文件夹
        """
        return os.path.basename(_object)

    @staticmethod
    def dir_name(_object: str):
        """
        获取对象所在文件夹的绝对路径，对象可以是文件，也可以是文件夹
        """
        return os.path.dirname(_object)

    @staticmethod
    def abspath(_object: str):
        """
        获取对象的绝对路径，对象可以是文件，也可以是文件夹
        """
        return os.path.abspath(_object)

    @staticmethod
    def path_join(*_path):
        """
        替代os.path.join
        """
        return os.path.join(*_path)

    @staticmethod
    def file_walk(_path, pattern: str = None):
        """
        遍历文件
        """
        for root, dirs, files in os.walk(_path):
            if pattern:
                for file in files:
                    if file.endswith(pattern):
                        relative_path = os.path.join(root, file)
                        yield relative_path

    @staticmethod
    def file_walk_with_join_dir_and_file(_path, pattern: str = None):
        """

        """
        for root, dirs, files in os.walk(_path):
            if pattern:
                new_files = list()
                for file in files:
                    if file.endswith(pattern):
                        new_files.append(file)
                for _file in new_files:
                    relative_path = PathManager.path_join(root, _file)
                    yield relative_path
            else:
                for _file in files:
                    relative_path = PathManager.path_join(root, _file)
                    yield relative_path

    @staticmethod
    def sub_dir_file_exists_or_error(parent_path: str, sub_dir_or_file_name: str):
        """

        """
        full_path = os.path.join(parent_path, sub_dir_or_file_name)
        if not os.path.join(full_path):
            raise FileNotFoundError(f"no such file or directory: '{sub_dir_or_file_name}' in '{parent_path}'")

        return full_path

    @staticmethod
    def path_exists(_path):
        """
        替代os.path.exists
        :param _path:
        :return:
        """
        return os.path.exists(_path)

    @staticmethod
    def is_dir(_path):
        """
        替代os.path.isdir
        :param _path:
        :return:
        """
        return os.path.isdir(_path)

    @staticmethod
    def is_file(_path):
        """
        替代os.path.isfile
        :param _path:
        :return:
        """
        return os.path.isfile(_path)
